package edu.uob;


import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Select {

    public static String resultToString(Object[][] result) {
        StringBuilder sb = new StringBuilder();
        if (result != null) {
            for (Object[] row : result) {
                for (Object item : row) {
                    sb.append(item).append("\t");
                }
                sb.append("\n");
            }
        } else {
            sb.append("Result is empty.\n");
        }
        return sb.toString();
    }

    public static Object[][] executeQuery(DataTable dataTable, String[] tokens) {
        Object[][] result; // 行列合并为一个二维数组

        if (tokens.length < 4 || !tokens[0].equalsIgnoreCase("SELECT") || !tokens[2].equalsIgnoreCase("FROM")) {
            System.err.println("Invalid query format.");
            return null; // 查询格式错误，返回空结果
        }

        String WildAttribList = tokens[1];
        boolean hasWhereClause = tokens.length > 5 && tokens[4].equalsIgnoreCase("WHERE");


        if (hasWhereClause) {
            StringBuilder allCondition = new StringBuilder();
            for (int i = 5; i < tokens.length; i++) {
                allCondition.append(tokens[i]);
            }

            result = handleCondition(dataTable, allCondition.toString());

        } else {
            result = handleWhere(dataTable);
        }

        if (result == null) {
            System.err.println("[ERROR] Error executing query.");
            return null;
        }

        if(!WildAttribList.contains("*")){
            result = handleWildAttribList(result, WildAttribList,dataTable.getColumnNames());
        }
        return result;
    }

    private static Object[][] handleWildAttribList(Object[][] result, String wildAttribList,List<String> columnNames) {
        // 找到 wildAttribList 在列名列表中的索引
        String[] wildAttributes = wildAttribList.split(",");
        Object[][] newResult = new Object[result.length][wildAttributes.length];

        for (int j = 0; j < wildAttributes.length; j++) {
            int columnIndex = columnNames.indexOf(wildAttributes[j]);

            // 如果找到了列名，则将相应列的数据添加到新的结果数组中
            if (columnIndex != -1) {
                for (int i = 0; i < result.length; i++) {
                    newResult[i][j] = result[i][columnIndex];
                }
            } else {
                // 如果未找到列名，则将相应位置设置为 null
                for (int i = 0; i < result.length; i++) {
                    newResult[i][j] = null;
                }
            }
        }
        return newResult;
    }


    private static Object[][] handleWhere(DataTable dataTable) {
        Object[][] result = new Object[dataTable.getData().length + 1][];
        result[0] = dataTable.getColumnNames().toArray(new String[0]); // 添加列名到第一行
        System.arraycopy(dataTable.getData(), 0, result, 1, dataTable.getData().length); // 将数据复制到结果数组中
        return result;
    }

    private static Object[][] handleCondition(DataTable dataTable, String allCondition) {

        String cleanedCondition = allCondition.replaceAll("[()]", "");
        cleanedCondition = cleanedCondition.replaceAll("\\s+", "");
        // 使用正则表达式分割字符串为单个条件
        String[] conditions = cleanedCondition.split("(?=(AND|OR))|(?<=(AND|OR))");

        // 初始化存储 AND 和 OR 操作符的数组
        String[] operators = new String[conditions.length];
        // 初始化存储条件的数组
        String[] conditionArray = new String[conditions.length];

        int operatorIndex = 0;
        int conditionIndex = 0;

        for (String str : conditions) {
            if (str.equals("AND") || str.equals("OR")) {
                operators[operatorIndex++] = str;
            } else {
                conditionArray[conditionIndex++] = str;
            }
        }

        if (operatorIndex != conditionIndex - 1) {
            throw new IllegalArgumentException("Number of operators should be one less than number of conditions.");
        }

        operators = Arrays.stream(operators).filter(Objects::nonNull).toArray(String[]::new);
        conditionArray = Arrays.stream(conditionArray).filter(Objects::nonNull).toArray(String[]::new);

        Object[][] result = null; // 初始化二维数组
        int resultCount = 0; // 记录满足条件的行数据数量

        for (Object[] rowData : dataTable.getData()) {
            Boolean[] booleanArray = new Boolean[conditionArray.length]; // 初始化布尔数组
            for (int i = 0; i < conditionArray.length; i++) {
                booleanArray[i] = satisfiesCondition(dataTable.getColumnNames(), rowData, conditionArray[i]);
            }

            System.out.println("booleanArray   " + Arrays.toString(booleanArray));

            String restoredExpression = restoreExpression(allCondition, booleanArray);

            if (evaluateExpression(restoredExpression)) {
                // 如果满足条件，则将行数据添加到结果中
                if (result == null) {
                    // 如果结果数组尚未初始化，则初始化为包含一行的二维数组
                    result = new Object[1][rowData.length];
                } else {
                    // 如果结果数组已经初始化，则动态调整大小以容纳新的行数据
                    result = Arrays.copyOf(result, resultCount + 1);
                }
                result[resultCount++] = rowData; // 将行数据添加到结果数组中
            }

        }

        if (result != null) {
            // 如果 result 不为空，则在第一行添加 columnNames
            Object[][] newResult = new Object[result.length + 1][];
            newResult[0] = dataTable.getColumnNames().toArray(new String[0]); // 将 columnNames 转换为数组并添加到新结果的第一行
            System.arraycopy(result, 0, newResult, 1, result.length); // 复制原来的 result 到新的结果中
            result = newResult; // 更新 result
        }

        return result;
    }

    public static boolean evaluateExpression(String expression) {
        System.out.println("expression"+ expression);
        expression = expression.replaceAll("TRUE", "T").replaceAll("FALSE", "F").replaceAll("AND", "&").replaceAll("OR", "|");

        Stack<Character> operatorStack = new Stack<>();
        Stack<Boolean> operandStack = new Stack<>();

        for (char c : expression.toCharArray()) {
            if (c == 'T' || c == 'F') {
                operandStack.push(c == 'T');
            } else if (c == '(') {
                operatorStack.push(c);
            } else if (c == ')') {
                while (operatorStack.peek() != '(') {
                    evaluate(operandStack, operatorStack);
                }
                operatorStack.pop(); // Pop the
            } else if (c == '&' || c == '|') {
                while (!operatorStack.isEmpty() && precedence(operatorStack.peek()) >= precedence(c)) {
                    evaluate(operandStack, operatorStack);
                }
                operatorStack.push(c);
            }
        }

        while (!operatorStack.isEmpty()) {
            evaluate(operandStack, operatorStack);
        }

        return operandStack.pop();
    }

    private static void evaluate(Stack<Boolean> operandStack, Stack<Character> operatorStack) {
        char operator = operatorStack.pop();
        boolean operand2 = operandStack.pop();
        boolean operand1 = operandStack.pop();
        if (operator == '&') {
            operandStack.push(operand1 && operand2);
        } else if (operator == '|') {
            operandStack.push(operand1 || operand2);
        }
    }

    private static int precedence(char operator) {
        if (operator == '&') {
            return 2;
        } else if (operator == '|') {
            return 1;
        }
        return 0; // '('
    }

    public static String restoreExpression(String allCondition, Boolean[] booleanArray) {
        allCondition = allCondition.replaceAll("\\s", ""); // 去除表达式中的所有空格

        StringBuilder restoredExpression = new StringBuilder();
        Pattern pattern = Pattern.compile("\\(|\\)|\\b(AND|OR)\\b|[^\\s()]+");
        Matcher matcher = pattern.matcher(allCondition);

        int index = 0;
        while (matcher.find()) {
            if (matcher.group().matches("AND|OR|\\(|\\)")) {
                // 如果是AND、OR、括号等连接词，则直接附加到结果中
                restoredExpression.append(matcher.group());
            } else {
                // 否则，匹配到条件部分，替换为对应的布尔值
                if (index < booleanArray.length) {
                    restoredExpression.append(booleanArray[index] ? "TRUE" : "FALSE");
                    index++; // 确保索引增加在合法范围内
                } else {
                    throw new IllegalArgumentException("Boolean array index out of bounds");
                }
            }
        }
        return restoredExpression.toString();
    }

    public static boolean evaluateExpression(String[] operators, Boolean[] booleanArray) {
        if (operators.length != booleanArray.length - 1) {
            throw new IllegalArgumentException("Number of operators should be one less than number of boolean values.");
        }
        boolean result = booleanArray[0];
        for (int i = 0; i < operators.length; i++) {
            boolean nextValue = booleanArray[i + 1];
            result = switch (operators[i]) {
                case "AND" -> result && nextValue;
                case "OR" -> result || nextValue;
                default -> throw new IllegalArgumentException("Invalid operator: " + operators[i]);
            };
        }
        return result;
    }

    static boolean satisfiesCondition(List<String> columnNames, Object[] rowData, String condition) {
        condition = condition.trim();
        // Split by comparison operators

        String[] parts = condition.split("(?<=(==|>|<|>=|<=|!=|LIKE)|(?=(==|>|<|>=|<=|!=|LIKE)))\\s*", 3);

        int conditionIndex = -1;

        for (int i = 0; i < columnNames.size(); i++) {
            if (columnNames.get(i).equals(parts[0])) {
                conditionIndex = i;
                break;
            }
        }

        if (conditionIndex == -1) {
            System.err.println("Error: Column " + parts[0] + " specified in condition not found.");
            return false;
        }

        String tableValue = (String) rowData[conditionIndex];
        String conditionValue = parts[2];
        String conditionType;

        String[] type ={"string","int"};

        if (conditionValue.contains("'") || conditionValue.contains("TRUE") || conditionValue.contains("FALSE") || conditionValue.contains("NULL")){
            conditionType = type[0];
        } else {
            conditionType = type[1];
        }

        if(!parts[1].contains("LIKE")){//无like
            if(conditionType.contains("string")){
                String cleanConditionValue = conditionValue.replaceAll("'", "");
                return compareStrings(tableValue,cleanConditionValue,parts[1]);
                //按字符串处理
            } else {
                //按照数字处理
                return compareNumbers( tableValue,conditionValue,parts[1]);
            }
        }else {//like 都按字符串匹配
            String cleanConditionValue = conditionValue.replaceAll("'", "");
            return tableValue.contains(cleanConditionValue);
        }

    }

    public static boolean compareNumbers(String num1, String num2, String operator) {
        // 获取正负号
        int sign1 = num1.startsWith("+") ? 1 : num1.startsWith("-") ? -1 : 1;
        int sign2 = num2.startsWith("+") ? 1 : num2.startsWith("-") ? -1 : 1;

        // 移除正负号
        String cleanNum1 = removeSign(num1);
        String cleanNum2 = removeSign(num2);

        // 转换为数字类型
        double value1 = Double.parseDouble(cleanNum1) * sign1;
        double value2 = Double.parseDouble(cleanNum2) * sign2;

        // 执行比较
        return switch (operator) {
            case "==" -> value1 == value2;
            case ">" -> value1 > value2;
            case "<" -> value1 < value2;
            case ">=" -> value1 >= value2;
            case "<=" -> value1 <= value2;
            case "!=" -> value1 != value2;
            default -> throw new IllegalArgumentException("Invalid operator: " + operator);
        };
    }

    private static String removeSign(String num) {
        if (num.startsWith("+") || num.startsWith("-")) {
            return num.substring(1);
        } else {
            return num;
        }
    }

    public static boolean compareStrings(String str1, String str2, String operator) {
        // 执行比较
        return switch (operator) {
            case "==" -> str1.equals(str2);
            case "!=" -> !str1.equals(str2);
            case ">" -> str1.compareTo(str2) > 0;
            case "<" -> str1.compareTo(str2) < 0;
            case ">=" -> str1.compareTo(str2) >= 0;
            case "<=" -> str1.compareTo(str2) <= 0;
            default -> throw new IllegalArgumentException("Invalid operator: " + operator);
        };
    }
}


